package com.xiaowu.friend.manager;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.xiaowu.common.core.constants.CacheConstants;
import com.xiaowu.common.core.domain.PageQueryDTO;
import com.xiaowu.common.redis.service.RedisService;
import com.xiaowu.friend.domain.message.MessageText;
import com.xiaowu.friend.domain.message.vo.MessageTextVO;
import com.xiaowu.friend.mapper.message.MessageTextMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
public class MessageCacheManager {

    // 注入RedisService
    @Autowired
    private RedisService redisService;

    // 注入MessageTextMapper
    @Autowired
    private MessageTextMapper messageTextMapper;

    // 刷新缓存
    public void refreshCache(Long userId) {
        // 从数据库中获取用户消息列表
        List<MessageTextVO> messageTextVOList = messageTextMapper.selectUserMsgList(userId);
        // 如果消息列表为空，则直接返回
        if (CollectionUtil.isEmpty(messageTextVOList)) {
            return;
        }
        // 获取消息ID列表
        List<Long> textIdList = messageTextVOList.stream()
                .map(MessageTextVO::getTextId).toList();
        // 获取用户消息列表的key
        String userMsgListKey = getUserMsgListKey(userId);
        // 将消息ID列表存入Redis
        redisService.rightPushAll(userMsgListKey, textIdList);
        // 将消息详情存入Redis
        Map<String, MessageTextVO> messageTextVOMap = new HashMap<>();
        for (MessageTextVO messageTextVO : messageTextVOList) {
            messageTextVOMap.put(getMsgDetailKey(messageTextVO.getTextId()), messageTextVO);
        }
        redisService.multiSet(messageTextVOMap);
    }

    // 获取消息列表
    public List<MessageTextVO> getMsgTextVOList(PageQueryDTO dto, Long userId) {
        // 计算起始位置和结束位置
        int start = (dto.getPageNum() - 1) * dto.getPageSize();
        int end = start + dto.getPageSize() - 1;
        // 获取用户消息列表的key
        String userMsgListKey = getUserMsgListKey(userId);
        // 从Redis中获取消息ID列表
        List<Long> msgTextIdList = redisService
                .getCacheListByRange(userMsgListKey, start, end, Long.class);
        // 组装消息列表
        List<MessageTextVO> messageTextVOList = assembleMsgTextVOList(msgTextIdList);
        // 如果消息列表为空，则从数据库中获取并刷新缓存
        if (CollectionUtil.isEmpty(messageTextVOList)) {
            messageTextVOList = getMsgTextVOListByDB(dto, userId);
            refreshCache(userId);
        }
        return messageTextVOList;
    }

    // 从数据库中获取消息列表
    private List<MessageTextVO> getMsgTextVOListByDB(PageQueryDTO dto, Long userId) {
        // 设置分页参数
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        // 从数据库中获取消息列表
        return messageTextMapper.selectUserMsgList(userId);
    }

    // 组装消息列表
    private List<MessageTextVO> assembleMsgTextVOList(List<Long> msgTextIdList) {
        // 如果消息ID列表为空，则说明Redis中没有数据，从数据库中查数据并刷新缓存
        if (CollectionUtil.isEmpty(msgTextIdList)) {
            //说明redis当中没数据 从数据库中查数据并且重新刷新缓存
            return null;
        }
        List<String> detailKeyList = new ArrayList<>();
        for (Long textId : msgTextIdList) {
            detailKeyList.add(getMsgDetailKey(textId));
        }
        List<MessageTextVO> messageTextVOList = redisService
                .multiGet(detailKeyList, MessageTextVO.class);
        CollUtil.removeNull(messageTextVOList);
        if (CollectionUtil.isEmpty(messageTextVOList) ||
                messageTextVOList.size() != msgTextIdList.size()) {
            //说明redis中数据有问题 从数据库中查数据并且重新刷新缓存
            return null;
        }
        return messageTextVOList;
    }

    public Long getListSize(Long userId) {
        return redisService.getListSize(getUserMsgListKey(userId));
    }

    private String getUserMsgListKey(Long userId) {
        return CacheConstants.USER_MESSAGE_LIST + userId;
    }

    private String getMsgDetailKey(Long textId) {
        return CacheConstants.MESSAGE_DETAIL + textId;
    }
}
